"""
移动端适配服务

提供移动端界面适配和优化功能，包括：
- 响应式布局适配
- 移动端UI组件优化
- 触摸交互支持
- 移动端性能优化
- 设备特性检测
- 移动端安全增强
"""
import json
import re
from typing import Dict, List, Any, Optional, Tuple
from datetime import datetime
from dataclasses import dataclass, field
from enum import Enum
import logging

# 配置日志
logging.basicConfig(level=logging.INFO)
mobile_logger = logging.getLogger('mobile_adapter')


class DeviceType(Enum):
    """设备类型枚举"""
    MOBILE = "mobile"
    TABLET = "tablet"
    DESKTOP = "desktop"
    UNKNOWN = "unknown"


class ScreenSize(Enum):
    """屏幕尺寸枚举"""
    SMALL = "small"      # < 576px
    MEDIUM = "medium"    # 576px - 768px
    LARGE = "large"      # 768px - 992px
    XLARGE = "xlarge"    # > 992px


class Orientation(Enum):
    """屏幕方向枚举"""
    PORTRAIT = "portrait"
    LANDSCAPE = "landscape"


@dataclass
class DeviceInfo:
    """设备信息"""
    device_type: DeviceType
    screen_width: int
    screen_height: int
    screen_size: ScreenSize
    orientation: Orientation
    user_agent: str
    platform: str = ""
    browser: str = ""
    version: str = ""
    supports_touch: bool = False
    supports_offline: bool = False
    network_type: str = "unknown"
    battery_level: Optional[float] = None


@dataclass
class MobileLayout:
    """移动端布局配置"""
    layout_id: str
    device_type: DeviceType
    screen_size: ScreenSize
    components: List[str] = field(default_factory=list)
    css_classes: List[str] = field(default_factory=list)
    breakpoints: Dict[str, int] = field(default_factory=dict)
    optimizations: Dict[str, Any] = field(default_factory=dict)


@dataclass
class TouchGesture:
    """触摸手势"""
    gesture_type: str  # tap, swipe, pinch, rotate
    start_x: float
    start_y: float
    end_x: float
    end_y: float
    duration: float
    velocity: float = 0.0
    scale: float = 1.0
    rotation: float = 0.0


class MobileAdapterService:
    """移动端适配服务"""
    
    def __init__(self):
        # 设备检测规则
        self.device_patterns = {
            DeviceType.MOBILE: [
                r'Mobile|Android|iPhone|iPod|BlackBerry|Windows Phone',
                r'Opera Mini|Opera Mobi'
            ],
            DeviceType.TABLET: [
                r'iPad|Android.*Tablet|Kindle|Silk|PlayBook'
            ]
        }
        
        # 屏幕尺寸断点
        self.breakpoints = {
            ScreenSize.SMALL: (0, 575),
            ScreenSize.MEDIUM: (576, 767),
            ScreenSize.LARGE: (768, 991),
            ScreenSize.XLARGE: (992, float('inf'))
        }
        
        # 移动端布局模板
        self.layout_templates = {}
        self._initialize_layout_templates()
        
        # 性能优化配置
        self.performance_config = {
            'enable_lazy_loading': True,
            'enable_image_compression': True,
            'enable_resource_bundling': True,
            'enable_caching': True,
            'max_image_size': 1024 * 1024,  # 1MB
            'max_bundle_size': 2 * 1024 * 1024,  # 2MB
            'cache_duration': 3600  # 1小时
        }
        
        # 触摸手势配置
        self.gesture_config = {
            'tap_threshold': 10,  # 像素
            'swipe_threshold': 50,  # 像素
            'pinch_threshold': 0.1,  # 缩放比例
            'long_press_duration': 500,  # 毫秒
            'double_tap_interval': 300  # 毫秒
        }
    
    def _initialize_layout_templates(self):
        """初始化布局模板"""
        # 移动端布局模板
        self.layout_templates[DeviceType.MOBILE] = {
            ScreenSize.SMALL: MobileLayout(
                layout_id="mobile_small",
                device_type=DeviceType.MOBILE,
                screen_size=ScreenSize.SMALL,
                components=[
                    "header_compact",
                    "navigation_bottom",
                    "content_single_column",
                    "sidebar_collapsible",
                    "footer_minimal"
                ],
                css_classes=[
                    "mobile-layout",
                    "single-column",
                    "compact-header",
                    "bottom-nav"
                ],
                breakpoints={
                    "xs": 0,
                    "sm": 576
                },
                optimizations={
                    "lazy_load_images": True,
                    "compress_css": True,
                    "minimize_js": True,
                    "enable_touch_gestures": True
                }
            ),
            ScreenSize.MEDIUM: MobileLayout(
                layout_id="mobile_medium",
                device_type=DeviceType.MOBILE,
                screen_size=ScreenSize.MEDIUM,
                components=[
                    "header_standard",
                    "navigation_side",
                    "content_two_column",
                    "sidebar_expandable",
                    "footer_standard"
                ],
                css_classes=[
                    "mobile-layout",
                    "two-column",
                    "standard-header",
                    "side-nav"
                ],
                breakpoints={
                    "sm": 576,
                    "md": 768
                },
                optimizations={
                    "lazy_load_images": True,
                    "compress_css": True,
                    "enable_touch_gestures": True
                }
            )
        }
        
        # 平板端布局模板
        self.layout_templates[DeviceType.TABLET] = {
            ScreenSize.LARGE: MobileLayout(
                layout_id="tablet_large",
                device_type=DeviceType.TABLET,
                screen_size=ScreenSize.LARGE,
                components=[
                    "header_full",
                    "navigation_top",
                    "content_three_column",
                    "sidebar_fixed",
                    "footer_full"
                ],
                css_classes=[
                    "tablet-layout",
                    "three-column",
                    "full-header",
                    "top-nav"
                ],
                breakpoints={
                    "md": 768,
                    "lg": 992
                },
                optimizations={
                    "enable_hover_effects": True,
                    "enable_animations": True,
                    "enable_touch_gestures": True
                }
            )
        }
    
    def detect_device(self, user_agent: str, screen_width: int = 0, 
                     screen_height: int = 0) -> DeviceInfo:
        """检测设备信息"""
        try:
            # 检测设备类型
            device_type = DeviceType.DESKTOP
            for dev_type, patterns in self.device_patterns.items():
                for pattern in patterns:
                    if re.search(pattern, user_agent, re.IGNORECASE):
                        device_type = dev_type
                        break
                if device_type != DeviceType.DESKTOP:
                    break
            
            # 确定屏幕尺寸
            screen_size = self._determine_screen_size(screen_width)
            
            # 确定屏幕方向
            orientation = (Orientation.LANDSCAPE if screen_width > screen_height 
                          else Orientation.PORTRAIT)
            
            # 解析浏览器信息
            browser_info = self._parse_browser_info(user_agent)
            
            # 检测功能支持
            supports_touch = device_type in [DeviceType.MOBILE, DeviceType.TABLET]
            supports_offline = self._check_offline_support(user_agent)
            
            device_info = DeviceInfo(
                device_type=device_type,
                screen_width=screen_width,
                screen_height=screen_height,
                screen_size=screen_size,
                orientation=orientation,
                user_agent=user_agent,
                platform=browser_info.get('platform', ''),
                browser=browser_info.get('browser', ''),
                version=browser_info.get('version', ''),
                supports_touch=supports_touch,
                supports_offline=supports_offline
            )
            
            mobile_logger.info(f"设备检测完成: {device_type.value} - {screen_size.value}")
            
            return device_info
            
        except Exception as e:
            mobile_logger.error(f"设备检测失败: {str(e)}")
            return DeviceInfo(
                device_type=DeviceType.UNKNOWN,
                screen_width=screen_width,
                screen_height=screen_height,
                screen_size=ScreenSize.MEDIUM,
                orientation=Orientation.PORTRAIT,
                user_agent=user_agent,
                supports_touch=False,
                supports_offline=False
            )
    
    def _determine_screen_size(self, width: int) -> ScreenSize:
        """确定屏幕尺寸"""
        for size, (min_width, max_width) in self.breakpoints.items():
            if min_width <= width <= max_width:
                return size
        return ScreenSize.MEDIUM
    
    def _parse_browser_info(self, user_agent: str) -> Dict[str, str]:
        """解析浏览器信息"""
        browser_patterns = {
            'Chrome': r'Chrome/(\d+\.\d+)',
            'Firefox': r'Firefox/(\d+\.\d+)',
            'Safari': r'Safari/(\d+\.\d+)',
            'Edge': r'Edge/(\d+\.\d+)',
            'Opera': r'Opera/(\d+\.\d+)'
        }
        
        platform_patterns = {
            'iOS': r'iPhone|iPad|iPod',
            'Android': r'Android',
            'Windows': r'Windows',
            'macOS': r'Macintosh|Mac OS X',
            'Linux': r'Linux'
        }
        
        browser_info = {'browser': 'Unknown', 'version': '', 'platform': 'Unknown'}
        
        # 检测浏览器
        for browser, pattern in browser_patterns.items():
            match = re.search(pattern, user_agent)
            if match:
                browser_info['browser'] = browser
                browser_info['version'] = match.group(1)
                break
        
        # 检测平台
        for platform, pattern in platform_patterns.items():
            if re.search(pattern, user_agent, re.IGNORECASE):
                browser_info['platform'] = platform
                break
        
        return browser_info
    
    def _check_offline_support(self, user_agent: str) -> bool:
        """检查离线支持"""
        # 简化的离线支持检测
        modern_browsers = ['Chrome', 'Firefox', 'Safari', 'Edge']
        return any(browser in user_agent for browser in modern_browsers)
    
    def get_adaptive_layout(self, device_info: DeviceInfo) -> Optional[MobileLayout]:
        """获取自适应布局"""
        try:
            device_layouts = self.layout_templates.get(device_info.device_type, {})
            layout = device_layouts.get(device_info.screen_size)
            
            if layout:
                # 根据设备特性调整布局
                optimized_layout = self._optimize_layout_for_device(layout, device_info)
                mobile_logger.info(f"获取布局: {optimized_layout.layout_id}")
                return optimized_layout
            
            # 回退到默认布局
            return self._get_fallback_layout(device_info)
            
        except Exception as e:
            mobile_logger.error(f"获取布局失败: {str(e)}")
            return None
    
    def _optimize_layout_for_device(self, layout: MobileLayout, 
                                   device_info: DeviceInfo) -> MobileLayout:
        """为设备优化布局"""
        optimized_layout = MobileLayout(
            layout_id=layout.layout_id,
            device_type=layout.device_type,
            screen_size=layout.screen_size,
            components=layout.components.copy(),
            css_classes=layout.css_classes.copy(),
            breakpoints=layout.breakpoints.copy(),
            optimizations=layout.optimizations.copy()
        )
        
        # 根据网络类型优化
        if hasattr(device_info, 'network_type') and device_info.network_type in ['2g', '3g']:
            optimized_layout.optimizations.update({
                'reduce_animations': True,
                'compress_images_aggressive': True,
                'minimize_requests': True
            })
        
        # 根据电池电量优化
        if hasattr(device_info, 'battery_level') and device_info.battery_level and device_info.battery_level < 0.2:
            optimized_layout.optimizations.update({
                'reduce_cpu_usage': True,
                'disable_animations': True,
                'reduce_polling': True
            })
        
        # 根据屏幕方向调整
        if device_info.orientation == Orientation.LANDSCAPE:
            if 'sidebar_collapsible' in optimized_layout.components:
                optimized_layout.components.remove('sidebar_collapsible')
                optimized_layout.components.append('sidebar_fixed')
        
        return optimized_layout
    
    def _get_fallback_layout(self, device_info: DeviceInfo) -> MobileLayout:
        """获取回退布局"""
        return MobileLayout(
            layout_id="fallback_layout",
            device_type=device_info.device_type,
            screen_size=device_info.screen_size,
            components=[
                "header_simple",
                "content_single_column",
                "footer_minimal"
            ],
            css_classes=[
                "fallback-layout",
                "single-column"
            ],
            breakpoints={"xs": 0, "sm": 576, "md": 768, "lg": 992},
            optimizations={
                "minimal_features": True,
                "basic_styling": True
            }
        )
    
    def generate_responsive_css(self, layout: MobileLayout) -> str:
        """生成响应式CSS"""
        try:
            css_rules = []
            
            # 基础样式
            css_rules.append(f"""
/* {layout.layout_id} 布局样式 */
.{layout.layout_id} {{
    width: 100%;
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}}
""")
            
            # 响应式断点
            for breakpoint, width in layout.breakpoints.items():
                if width > 0:
                    css_rules.append(f"""
@media (min-width: {width}px) {{
    .{layout.layout_id} {{
        max-width: {width}px;
        margin: 0 auto;
    }}
}}
""")
            
            # 组件样式
            for component in layout.components:
                css_rules.append(self._generate_component_css(component, layout))
            
            # 优化样式
            if layout.optimizations.get('enable_touch_gestures'):
                css_rules.append("""
/* 触摸优化 */
.touch-target {
    min-height: 44px;
    min-width: 44px;
    padding: 8px;
}

.touch-friendly {
    -webkit-tap-highlight-color: rgba(0,0,0,0.1);
    touch-action: manipulation;
}
""")
            
            if layout.optimizations.get('lazy_load_images'):
                css_rules.append("""
/* 图片懒加载 */
.lazy-image {
    opacity: 0;
    transition: opacity 0.3s;
}

.lazy-image.loaded {
    opacity: 1;
}
""")
            
            return '\n'.join(css_rules)
            
        except Exception as e:
            mobile_logger.error(f"生成CSS失败: {str(e)}")
            return ""
    
    def _generate_component_css(self, component: str, layout: MobileLayout) -> str:
        """生成组件CSS"""
        component_styles = {
            'header_compact': """
.header-compact {
    height: 56px;
    padding: 8px 16px;
    display: flex;
    align-items: center;
    justify-content: space-between;
}
""",
            'navigation_bottom': """
.navigation-bottom {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    height: 60px;
    background: #fff;
    border-top: 1px solid #e0e0e0;
    display: flex;
    justify-content: space-around;
    align-items: center;
    z-index: 1000;
}
""",
            'content_single_column': """
.content-single-column {
    padding: 16px;
    margin-bottom: 60px; /* 为底部导航留空间 */
}
""",
            'sidebar_collapsible': """
.sidebar-collapsible {
    position: fixed;
    top: 56px;
    left: -280px;
    width: 280px;
    height: calc(100vh - 56px);
    background: #fff;
    transition: left 0.3s ease;
    z-index: 999;
}

.sidebar-collapsible.open {
    left: 0;
}
""",
            'footer_minimal': """
.footer-minimal {
    padding: 16px;
    text-align: center;
    font-size: 12px;
    color: #666;
}
"""
        }
        
        return component_styles.get(component, f"/* {component} 样式待定义 */\n")
    
    def process_touch_gesture(self, gesture_data: Dict[str, Any]) -> TouchGesture:
        """处理触摸手势"""
        try:
            gesture = TouchGesture(
                gesture_type=gesture_data.get('type', 'tap'),
                start_x=gesture_data.get('startX', 0),
                start_y=gesture_data.get('startY', 0),
                end_x=gesture_data.get('endX', 0),
                end_y=gesture_data.get('endY', 0),
                duration=gesture_data.get('duration', 0),
                velocity=gesture_data.get('velocity', 0),
                scale=gesture_data.get('scale', 1.0),
                rotation=gesture_data.get('rotation', 0.0)
            )
            
            # 手势识别和处理
            processed_gesture = self._recognize_gesture(gesture)
            
            mobile_logger.info(f"处理手势: {processed_gesture.gesture_type}")
            
            return processed_gesture
            
        except Exception as e:
            mobile_logger.error(f"手势处理失败: {str(e)}")
            return TouchGesture(
                gesture_type='unknown',
                start_x=0, start_y=0,
                end_x=0, end_y=0,
                duration=0
            )
    
    def _recognize_gesture(self, gesture: TouchGesture) -> TouchGesture:
        """识别手势类型"""
        dx = abs(gesture.end_x - gesture.start_x)
        dy = abs(gesture.end_y - gesture.start_y)
        distance = (dx ** 2 + dy ** 2) ** 0.5
        
        # 点击手势
        if distance < self.gesture_config['tap_threshold']:
            if gesture.duration > self.gesture_config['long_press_duration']:
                gesture.gesture_type = 'long_press'
            else:
                gesture.gesture_type = 'tap'
        
        # 滑动手势
        elif distance > self.gesture_config['swipe_threshold']:
            if dx > dy:
                gesture.gesture_type = 'swipe_horizontal'
            else:
                gesture.gesture_type = 'swipe_vertical'
        
        # 缩放手势
        elif abs(gesture.scale - 1.0) > self.gesture_config['pinch_threshold']:
            if gesture.scale > 1.0:
                gesture.gesture_type = 'pinch_out'
            else:
                gesture.gesture_type = 'pinch_in'
        
        return gesture
    
    def optimize_for_mobile(self, content: str, device_info: DeviceInfo) -> str:
        """为移动端优化内容"""
        try:
            optimized_content = content
            
            # 图片优化
            if self.performance_config['enable_image_compression']:
                optimized_content = self._optimize_images(optimized_content, device_info)
            
            # 文本优化
            optimized_content = self._optimize_text_for_mobile(optimized_content)
            
            # 链接优化
            optimized_content = self._optimize_links_for_touch(optimized_content)
            
            # 表单优化
            optimized_content = self._optimize_forms_for_mobile(optimized_content)
            
            mobile_logger.info("移动端内容优化完成")
            
            return optimized_content
            
        except Exception as e:
            mobile_logger.error(f"移动端优化失败: {str(e)}")
            return content
    
    def _optimize_images(self, content: str, device_info: DeviceInfo) -> str:
        """优化图片"""
        # 添加响应式图片属性
        img_pattern = r'<img([^>]*?)src="([^"]*)"([^>]*?)>'
        
        def replace_img(match):
            attrs_before = match.group(1)
            src = match.group(2)
            attrs_after = match.group(3)
            
            # 添加响应式和懒加载属性
            new_attrs = []
            if 'class=' not in attrs_before + attrs_after:
                new_attrs.append('class="lazy-image responsive-image"')
            if 'loading=' not in attrs_before + attrs_after:
                new_attrs.append('loading="lazy"')
            if 'alt=' not in attrs_before + attrs_after:
                new_attrs.append('alt=""')
            
            new_attrs_str = ' ' + ' '.join(new_attrs) if new_attrs else ''
            
            return f'<img{attrs_before}src="{src}"{attrs_after}{new_attrs_str}>'
        
        return re.sub(img_pattern, replace_img, content)
    
    def _optimize_text_for_mobile(self, content: str) -> str:
        """优化移动端文本"""
        # 添加移动端文本样式类
        content = re.sub(
            r'<p([^>]*?)>',
            r'<p\1 class="mobile-text">',
            content
        )
        
        # 优化标题
        content = re.sub(
            r'<h([1-6])([^>]*?)>',
            r'<h\1\2 class="mobile-heading">',
            content
        )
        
        return content
    
    def _optimize_links_for_touch(self, content: str) -> str:
        """优化触摸链接"""
        # 为链接添加触摸友好的类
        content = re.sub(
            r'<a([^>]*?)>',
            r'<a\1 class="touch-target touch-friendly">',
            content
        )
        
        return content
    
    def _optimize_forms_for_mobile(self, content: str) -> str:
        """优化移动端表单"""
        # 为输入框添加移动端优化属性
        input_optimizations = {
            'email': 'inputmode="email" autocomplete="email"',
            'tel': 'inputmode="tel" autocomplete="tel"',
            'number': 'inputmode="numeric"',
            'search': 'inputmode="search"'
        }
        
        for input_type, attrs in input_optimizations.items():
            pattern = f'<input([^>]*?)type="{input_type}"([^>]*?)>'
            replacement = f'<input\\1type="{input_type}"\\2 {attrs} class="mobile-input">'
            content = re.sub(pattern, replacement, content)
        
        return content
    
    def get_mobile_performance_metrics(self) -> Dict[str, Any]:
        """获取移动端性能指标"""
        return {
            'optimization_config': self.performance_config,
            'supported_devices': list(self.layout_templates.keys()),
            'supported_screen_sizes': [size.value for size in ScreenSize],
            'gesture_support': {
                'tap': True,
                'swipe': True,
                'pinch': True,
                'long_press': True,
                'double_tap': True
            },
            'features': {
                'responsive_layout': True,
                'touch_optimization': True,
                'offline_support': True,
                'lazy_loading': True,
                'image_compression': True,
                'css_optimization': True
            },
            'performance_targets': {
                'first_contentful_paint': '< 2s',
                'largest_contentful_paint': '< 4s',
                'cumulative_layout_shift': '< 0.1',
                'first_input_delay': '< 100ms'
            }
        }


# 示例使用
if __name__ == "__main__":
    # 创建移动端适配服务
    mobile_service = MobileAdapterService()
    
    print("=== 移动端适配服务测试 ===")
    
    # 测试设备检测
    test_user_agents = [
        "Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15",
        "Mozilla/5.0 (iPad; CPU OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15",
        "Mozilla/5.0 (Linux; Android 11; SM-G991B) AppleWebKit/537.36",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
    ]
    
    for ua in test_user_agents:
        device_info = mobile_service.detect_device(ua, 375, 667)
        print(f"设备类型: {device_info.device_type.value}")
        print(f"屏幕尺寸: {device_info.screen_size.value}")
        print(f"浏览器: {device_info.browser}")
        print(f"支持触摸: {device_info.supports_touch}")
        print("-" * 40)
    
    # 测试布局适配
    mobile_device = mobile_service.detect_device(test_user_agents[0], 375, 667)
    layout = mobile_service.get_adaptive_layout(mobile_device)
    
    if layout:
        print(f"布局ID: {layout.layout_id}")
        print(f"组件: {layout.components}")
        print(f"CSS类: {layout.css_classes}")
        
        # 生成CSS
        css = mobile_service.generate_responsive_css(layout)
        print(f"生成CSS长度: {len(css)} 字符")
    
    # 获取性能指标
    metrics = mobile_service.get_mobile_performance_metrics()
    print(f"\n性能指标: {json.dumps(metrics, indent=2, ensure_ascii=False)}")